<template>
  <canvas ref="canvasRef" />
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, onUnmounted } from 'vue'

export default defineComponent({
  name: 'CanvasStars',
  setup() {
    const canvasRef = ref<HTMLCanvasElement | null>(null)

    let ctx: CanvasRenderingContext2D | null = null
    let canvas2: HTMLCanvasElement | null = null
    let ctx2: CanvasRenderingContext2D | null = null
    let stars: Star[] = []

    const w = window.innerWidth
    const h = window.innerHeight
    const hue = 217
    const maxStars = 1400

    onMounted(() => {
      if (canvasRef.value) {
        canvasRef.value.width = w
        canvasRef.value.height = h
        ctx = canvasRef.value.getContext('2d')

        canvas2 = document.createElement('canvas')
        canvas2.width = 100
        canvas2.height = 100
        ctx2 = canvas2.getContext('2d') as CanvasRenderingContext2D

        const half = canvas2.width / 2
        const gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half)
        gradient2.addColorStop(0.025, '#fff')
        gradient2.addColorStop(0.1, `hsl(${hue}, 61%, 33%)`)
        gradient2.addColorStop(0.25, `hsl(${hue}, 64%, 6%)`)
        gradient2.addColorStop(1, 'transparent')
        ctx2.fillStyle = gradient2
        ctx2.beginPath()
        ctx2.arc(half, half, half, 0, Math.PI * 2)
        ctx2.fill()

        // Initialize stars
        for (let i = 0; i < maxStars; i++) {
          stars.push(new Star())
        }

        animate()
      }
    })

    function animate() {
      if (!ctx || !ctx2) return

      ctx.globalCompositeOperation = 'source-over'
      ctx.globalAlpha = 0.8
      ctx.fillStyle = `hsla(${hue}, 64%, 6%, 1)`
      ctx.fillRect(0, 0, w, h)

      ctx.globalCompositeOperation = 'lighter'
      stars.forEach((star) => star.draw())

      requestAnimationFrame(animate)
    }

    function random(min: number, max?: number): number {
      if (max === undefined) {
        max = min
        min = 0
      }
      if (min > max) {
        ;[min, max] = [max, min]
      }
      return Math.floor(Math.random() * (max - min + 1)) + min
    }

    class Star implements Star {
      orbitRadius: number
      radius: number
      orbitX: number
      orbitY: number
      timePassed: number
      speed: number
      alpha: number

      constructor() {
        this.orbitRadius = random(w / 2 - 50)
        this.radius = random(100, this.orbitRadius) / 10
        this.orbitX = w / 2
        this.orbitY = h / 2
        this.timePassed = random(0, maxStars)
        this.speed = random(this.orbitRadius) / 900000
        this.alpha = random(2, 10) / 10
      }

      draw() {
        const x = Math.sin(this.timePassed + 1) * this.orbitRadius + this.orbitX
        const y = (Math.cos(this.timePassed) * this.orbitRadius) / 2 + this.orbitY
        const twinkle = random(10)

        if (twinkle === 1 && this.alpha > 0) {
          this.alpha -= 0.05
        } else if (twinkle === 2 && this.alpha < 1) {
          this.alpha += 0.05
        }

        ctx!.globalAlpha = this.alpha
        ctx!.drawImage(canvas2!, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius)
        this.timePassed += this.speed
      }
    }

    onUnmounted(() => {
      // Clean up resources if needed
    })

    return { canvasRef }
  }
})
</script>

<style lang="scss" scoped>
body {
  background: red;
  overflow: hidden;
}
</style>
